﻿namespace AbpPlusPlus
{
    using System;
    using System.Collections.Generic;
    using System.IO;

    using Abp;
    using Abp.Modules;
    using Abp.Reflection.Extensions;

    using Castle.MicroKernel.Registration;
    using Castle.MicroKernel.Resolvers.SpecializedResolvers;

    using MediatR;
    using MediatR.Pipeline;

    [DependsOn(typeof(AbpKernelModule))]
    public class AbpMediatRModule: AbpModule
    {
        public override void PreInitialize()
        {
            this.IocManager.IocContainer.Kernel.Resolver.AddSubResolver(new CollectionResolver(this.IocManager.IocContainer.Kernel));
            this.IocManager.IocContainer.Kernel.AddHandlersFilter(new ContravariantFilter());
            
            this.IocManager.IocContainer.Register(Component.For<IMediator>().ImplementedBy<Mediator>());
            this.IocManager.IocContainer.Register(Component.For<TextWriter>().Instance(Console.Out));
            this.IocManager.IocContainer.Register(Component.For<SingleInstanceFactory>().UsingFactoryMethod<SingleInstanceFactory>(k => t => k.Resolve(t)));
            this.IocManager.IocContainer.Register(Component.For<MultiInstanceFactory>().UsingFactoryMethod<MultiInstanceFactory>(k => t => (IEnumerable<object>)k.ResolveAll(t)));
            
            this.IocManager.IocContainer.Register(Component.For(typeof(IPipelineBehavior<,>)).ImplementedBy(typeof(RequestPreProcessorBehavior<,>)).NamedAutomatically("PreProcessorBehavior"));
            this.IocManager.IocContainer.Register(Component.For(typeof(IPipelineBehavior<,>)).ImplementedBy(typeof(RequestPostProcessorBehavior<,>)).NamedAutomatically("PostProcessorBehavior"));
            this.IocManager.IocContainer.Register(Component.For(typeof(IPipelineBehavior<,>)).ImplementedBy(typeof(GenericPipelineBehavior<,>)).NamedAutomatically("Pipeline"));
            this.IocManager.IocContainer.Register(Component.For(typeof(IRequestPreProcessor<>)).ImplementedBy(typeof(GenericRequestPreProcessor<>)).NamedAutomatically("PreProcessor"));
            this.IocManager.IocContainer.Register(Component.For(typeof(IRequestPostProcessor<,>)).ImplementedBy(typeof(GenericRequestPostProcessor<,>)).NamedAutomatically("PostProcessor"));

        }

        public override void Initialize()
        {
            this.IocManager.RegisterAssemblyByConvention(typeof(AbpMediatRModule).GetAssembly());
        }
        
    }
}
